/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package io.renren.datasource.aspect;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import io.renren.datasource.annotation.DataSource;
import io.renren.datasource.config.DynamicContextHolder;

/**
 * 多数据源，切面处理类
 *
 * @author Mark sunlightcs@gmail.com
 */
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DataSourceAspect {
	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Pointcut("@annotation(io.renren.datasource.annotation.DataSource) " + "|| @within(io.renren.datasource.annotation.DataSource)")
	public void dataSourcePointCut() {

	}

	@Around("dataSourcePointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		MethodSignature signature = (MethodSignature) point.getSignature();
		Class targetClass = point.getTarget().getClass();
		Method method = signature.getMethod();

		DataSource targetDataSource = (DataSource) targetClass.getAnnotation(DataSource.class);
		DataSource methodDataSource = method.getAnnotation(DataSource.class);
		if (targetDataSource != null || methodDataSource != null) {
			String value;
			if (methodDataSource != null) {
				value = methodDataSource.value();
			} else {
				value = targetDataSource.value();
			}

			DynamicContextHolder.push(value);
			logger.debug("set datasource is {}", value);
		}

		try {
			return point.proceed();
		} finally {
			DynamicContextHolder.poll();
			logger.debug("clean datasource");
		}
	}
}